package com.study.easyexcel.business.template;

import com.alibaba.excel.util.ListUtils;
import com.alibaba.excel.util.MapUtils;
import com.study.easyexcel.common.RowGroupTemplate;
import com.study.easyexcel.common.domain.AxisParam;
import com.study.easyexcel.common.domain.GroupSubject;
import com.study.easyexcel.common.domain.ItemSubject;
import com.study.easyexcel.common.function.AxisFunction;

import java.util.List;
import java.util.Map;

/**
 * 平面组，拉平分组数据；在{@link RowGroupTemplate}的数据基础之上，将嵌套列表处理成单列表
 *
 * @author yuhuan
 * @date 2023/7/4
 */
public abstract class FlatGroupTemplate<T extends AxisParam> extends RowGroupTemplate<T> {

    /**
     * 行索引
     */
    private int rowIndex = 0;

    /**
     * 所有标题行的行索引
     */
    private final List<Integer> titleRowIndex = ListUtils.newArrayList();

    /**
     * 所有合计行的行索引
     */
    private final List<Integer> totalRowIndex = ListUtils.newArrayList();

    /**
     * 合计行的数据
     */
    protected Map<String, Object> totalRowData = MapUtils.newHashMap();

    public FlatGroupTemplate(AxisFunction<T, Map<String, Object>> source) {
        super(source);
    }

    /**
     * 数据组的起始行索引
     */
    public void initialIndex(int rowIndex) {
        this.rowIndex = rowIndex;
    }

    public List<Map<String, Object>> bodyFromVerticalGroup(GroupSubject groupSubject) {
        List<Map<String, Object>> groupData = ListUtils.newArrayList();
        // 插入单组数据的标题行
        Map<String, Object> titleRow = groupTitleRow(groupSubject.getGroupName(), groupSubject.getGroupAlias());
        groupData.add(titleRow);
        // 数据体，没有数据体时，留出一个空行
        if (groupSubject.getItemSubjects() == null || groupSubject.getItemSubjects().size() == 0) {
            groupData.add(getBlankRow());
            rowIndex++;
        }
        for (ItemSubject group : groupSubject.getItemSubjects()) {
            Map<String, Object> rowData = MapUtils.newHashMap();
            rowData.put(GROUP_NAME_KEY, group.getItemName());
            rowData.putAll(bodyFromHorizontalGroup(group.getItemId()));
            groupData.add(rowData);
            rowIndex++;
        }
        // 插入单组数据的合计行
        Map<String, Object> totalRow = groupTotalRow(groupSubject.getGroupName(), groupSubject.getGroupAlias());
        groupData.add(totalRow);
        return groupData;
    }

    public GroupSubject getGroupSubject(String groupName, String groupAlias) {
        GroupSubject groupSubject = new GroupSubject();
        groupSubject.setGroupName(groupName);
        groupSubject.setGroupAlias(groupAlias);
        groupSubject.setItemSubjects(getItemSubjects(groupName));
        return groupSubject;
    }

    /**
     * 标题行
     *
     * @param titleName 标题组名
     */
    public Map<String, Object> groupTitleRow(String groupName, String titleName) {
        this.titleRowIndex.add(this.rowIndex);
        rowIndex++;
        Map<String, Object> titleRow = getBlankRow();
        titleRow.put(GROUP_NAME_KEY, titleName);
        return titleRow;
    }

    /**
     * 合计行统计
     *
     * @param titleName 标题组名
     */
    public Map<String, Object> groupTotalRow(String groupName, String titleName) {
        this.totalRowIndex.add(this.rowIndex);
        rowIndex++;
        Map<String, Object> totalRow = getBlankRow();
        totalRow.put(GROUP_NAME_KEY, titleName + "合计");
        // 从外部提取合计数据
        if (this.totalRowData != null && this.totalRowData.size() != 0) {
            for (String alias : this.xAxisGroups.values()) {
                for (String column : this.keys) {
                    String key = getKey(alias, column);
                    Object data = this.totalRowData.get(groupName + key);
                    totalRow.put(key, data);
                }
            }
        }
        return totalRow;
    }

    /**
     * 获取单行所有列组的空白数据，用于标题行、合计行等不完整行的占位
     *
     * @return 单行空数据
     */
    private Map<String, Object> getBlankRow() {
        Map<String, Object> rowMap = MapUtils.newHashMap();
        rowMap.put(GROUP_NAME_KEY, null);
        for (String alias : this.xAxisGroups.values()) {
            for (String column : this.keys) {
                rowMap.put(getKey(alias, column), null);
                // 预留给空白单元格的样式填充占位符
                rowMap.put(getKey(alias, UniversalGroupStyle.STYLE_FILL_KEY), null);
            }
        }
        return rowMap;
    }

    public List<Integer> getTitleRowIndex() {
        return titleRowIndex;
    }

    public List<Integer> getTotalRowIndex() {
        return totalRowIndex;
    }

    public void setTotalRowData(Map<String, Object> totalRowData) {
        this.totalRowData = totalRowData;
    }
}
